import * as _ from "lodash"
import { OptionSelection } from "../catalog"
import httpClient from "../httpclient"

export class Cart {
  public id: string
  public items: CartItem[] = []

  constructor(id?: string, items?: CartItem[]) {
    if (id) {
      this.id = id
    }
    if (items) {
      this.items = items
    }
  }
}

export class CartItem {
  public id: string
  private store_id: string
  private product_id: string
  private variant_id: string
  public quantity: number
  public price: number
  public name: string
  private option_selections: OptionSelection[] = []
  private image_url: string
  public checked: boolean
  public added_time: string

  public get storeId() {
    return this.store_id
  }

  public set storeId(storeId) {
    this.store_id = storeId
  }

  public get variantId() {
    return this.variant_id
  }

  public set variantId(variantId) {
    this.variant_id = variantId
  }

  public get productId() {
    return this.product_id
  }

  public set productId(productId) {
    this.product_id = productId
  }

  public get imageUrl() {
    return this.image_url
  }

  public set imageUrl(value) {
    this.image_url = value
  }

  public get optionSelections() {
    return this.option_selections
  }

  public set optionSelections(optionSelections) {
    this.option_selections = optionSelections
  }

  public get addedTime() {
    return this.added_time
  }

  public set addedTime(addedTime) {
    this.added_time = addedTime
  }
}

export class CartItemAdjustment {
  private item_id: string
  private product_id: string
  private variant_id: string
  private quantity_delta: number

  public get itemId() {
    return this.item_id
  }

  public set itemId(itemId) {
    this.item_id = itemId
  }

  public get productId() {
    return this.product_id
  }

  public set productId(productId) {
    this.product_id = productId
  }

  public get variantId() {
    return this.variant_id
  }

  public set variantId(variantId) {
    this.variant_id = variantId
  }

  public get quantityDelta() {
    return this.quantity_delta
  }

  public set quantityDelta(quantityDelta) {
    this.quantity_delta = quantityDelta
  }

}

export class CartServiceV1 {

  public static getCart(cartId: string): Promise<Cart> {
    return httpClient.get(`/v1/carts/${cartId}`)
      .then(({ data }) => {
        return data
          ? new Cart(data.id, _.map(data.items, item => _.assign(new CartItem(), item)))
          : new Cart(cartId, [])
      })
  }

  public static checkCartItem(cart: string, itemId: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/${itemId}/check`).then(({ data }) => data)
  }

  public static updateCartItem(cart: string, item: CartItem): Promise<void> {
    return httpClient.patch(`/v1/carts/${cart}/items/${item.id}`, item).then(({ data }) => data)
  }

  public static adjustCartItem(cart: string, adjustment: CartItemAdjustment): Promise<void> {
    const url = _.isEmpty(adjustment.itemId)
      ? `/v1/carts/${cart}/items/adjust`
      : `/v1/carts/${cart}/items/${adjustment.itemId}/adjust`
    return httpClient.post(url, adjustment).then(({ data }) => data)
  }

  public static uncheckCartItem(cart: string, itemId: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/${itemId}/uncheck`).then(({ data }) => data)
  }

  public static checkCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/check/batch`, itemIds).then(({ data }) => data)
  }

  public static uncheckCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/uncheck/batch`, itemIds).then(({ data }) => data)
  }

  public static checkAllCartItems(cart: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/check`).then(({ data }) => data)
  }

  public static uncheckAllCartItems(cart: string): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/uncheck`).then(({ data }) => data)
  }

  public static addCartItem(cart: string, item: CartItem): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items`, item)
      .then(({ data }) => data)
  }

  public static addCartItems(cart: string, items: CartItem[]): Promise<void> {
    return httpClient.post(`/v1/carts/${cart}/items/batch`, items)
      .then(({ data }) => data)
  }

  public static removeCartItems(cart: string, itemIds: string[]): Promise<void> {
    return httpClient.delete(`/v1/carts/${cart}/items/batch`, { data: itemIds })
      .then(({ data }) => data)
  }
}
